package com.sc.nft.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.SecondEquityPropConfConfDetailsVO;
import com.sc.nft.entity.vo.secondEquityProp.MyConsignEquityPropsPageVO;
import com.sc.nft.entity.vo.secondEquityProp.SecondEquityPropBuyProductPageVO;
import com.sc.nft.entity.vo.secondEquityProp.SecondEquityPropConfPageVO;
import com.sc.nft.entity.vo.secondEquityProp.SecondEquityPropSearchConfVO;
import com.sc.nft.enums.ConSignStatus;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.UserEquityConsignStatusEnum;
import com.sc.nft.enums.UserEquityPropsHoldingStatusEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.SecondEquityPropsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * 二级-权益道具寄售表服务接口实现
 *
 * @author Sun
 * @since 2024-04-07 14:17:52
 * @description 由 Mybatisplus Code Generator 创建
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SecondEquityPropsServiceImpl implements SecondEquityPropsService {

    private final SecondEquityPropsDao secondEquityPropsDao;
    private final UserEquityPropsDao userEquityPropsDao;
    private final Redisson redisson;
    private final EquityPropsDao equityPropsDao;
    private final SecondEquityPropsConfigDao secondEquityPropsConfigDao;
    private final StaticDataDao staticDataDao;
    private final SecondEquityPropsOrderDao secondEquityPropsOrderDao;

    @Override
    public Page<MyConsignEquityPropsPageVO> myConsignEquityPropsPage(UserInfo user, Page page,Integer type) {
        return secondEquityPropsDao.myConsignEquityPropsPage(user.getId(),page,type);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchCancelConsignEquityProps(UserInfo user, List<Long> secondProductIds) {
        for (Long secondProductId : secondProductIds) {
            cancelConsignEquityProps(user, secondProductId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelConsignEquityProps(UserInfo user, Long secondProductid) {
        //这里要用下单的锁,防止下架了,但是还是被用户锁单
        Lock lock = redisson.getLock(RedisKeyEnum.LOCK_CONSIGN_EQUITY_PROPS.getKey() + user.getId());
        try {
            boolean res = lock.tryLock(10,  TimeUnit.SECONDS);
            if (!res) {
                throw new GlobalRunTimeException("系统繁忙,请稍后重试");
            }

             Assert.isFalse(
              secondEquityPropsOrderDao.getIsLockBysecondProductid(secondProductid),
              () -> new GlobalRunTimeException("权益道具已被锁定,请稍后重试"));

            SecondEquityProps secondEquityProps = secondEquityPropsDao.getUserEquityPropIdsByIdsAndUserId(user.getId(), secondProductid);
            Assert.notNull(secondEquityProps,()-> new GlobalRunTimeException("系统繁忙,请稍后重试"));
            Assert.isTrue(secondEquityProps.getStatus() == ConSignStatus.ON_SALES,()->new GlobalRunTimeException("权益道具已出售"));

            UserEquityProps userEquityProps = userEquityPropsDao.getById(secondEquityProps.getUserEquityPropsId());
            Assert.notNull(userEquityProps,()-> new GlobalRunTimeException("系统繁忙,请稍后重试"));
            Assert.isTrue(userEquityProps.getOnConsign() == UserEquityConsignStatusEnum.ON_CONSIGN,()->new GlobalRunTimeException("权益道具已出售"));
            Assert.isTrue(userEquityProps.getHoldingStatus() == UserEquityPropsHoldingStatusEnum.NORMAL,()->new GlobalRunTimeException("权益道具已出售"));

            //二级下架
            Assert.isTrue(secondEquityPropsDao.cancelConsignBySecondProductId(user.getId(),secondEquityProps.getId(),ConSignStatus.CANCEL),()->new GlobalRunTimeException("取消寄售失败,请稍后重试"));
            //修改用户道具表
            Assert.isTrue(userEquityPropsDao.cancelConsignByUserEquityPropId(user.getId(),userEquityProps.getId(),UserEquityConsignStatusEnum.NOT_CONSIGN),()->new GlobalRunTimeException("取消寄售失败,请稍后重试"));

        } catch (InterruptedException e) {
            log.error(StrUtil.format("寄售权益道具异常:{}",e));
            throw new GlobalRunTimeException("系统繁忙,请稍后重试");
        } finally {
            lock.unlock();
        }
    }


    @Override
    public Page<SecondEquityPropSearchConfVO> searchProduct(String firstTitle, Page page) {
        return secondEquityPropsDao.searchProduct(firstTitle,page);
    }

    @Override
    public Page<SecondEquityPropConfPageVO> productPage(Page page) {
        return secondEquityPropsDao.productPage(page);
    }

    @Override
    public SecondEquityPropConfConfDetailsVO confDetails(Long secondConfId) {
        SecondEquityPropsConfig config = secondEquityPropsConfigDao.getById(secondConfId);
        Assert.notNull(config,()->new GlobalRunTimeException("权益道具配置不存在"));
        Assert.isTrue(config.getStatus(),()->new GlobalRunTimeException("权益道具已出售"));

        EquityProps equityProps = equityPropsDao.getById(config.getEquityPropsId());
        Assert.notNull(equityProps,()->new GlobalRunTimeException("权益道具不存在"));

        StaticData staticData = staticDataDao.getByType("equity_prop_consign_rule");

        SecondEquityPropConfConfDetailsVO vo = new SecondEquityPropConfConfDetailsVO();
        vo.setSecondConfId(config.getId());
        vo.setEquityPropsId(equityProps.getId());
        vo.setFirstTitle(equityProps.getFirstTitle());
        vo.setCreationContent(equityProps.getCreationContent());
        vo.setConsignmentRule(ObjectUtil.isNull(staticData) ? StrUtil.EMPTY : staticData.getValue());


        return vo;
    }

    @Override
    public Page<SecondEquityPropBuyProductPageVO> getBuyProductPage(UserInfo user, Page page,Long secondConfId,Integer sort) {
        return secondEquityPropsDao.getBuyProductPage(page,secondConfId,sort);
    }



}